#include "stdafx.h"
#include <stdio.h>
#include "bitmap.h"

acl::atomic_long BitMap::testNum_ = 0; 
long long BitMap::TestGetNum()
{
    return testNum_.value(); 
} 

BitMap::BitMap(void* buf, size_t len)
: m_bmp(NULL)
, m_size(len)
, m_count(0)
{
    testNum_++;
    m_bmp = new unsigned char[(len + 7) / 8];
    memcpy(m_bmp, buf, (len + 7) / 8);
    ReCount();
}

BitMap::BitMap(size_t len)
: m_bmp(NULL)
, m_size(len)
, m_count(0)
{
    testNum_++;
    m_bmp = new unsigned char[(len + 7) / 8];
    memset(m_bmp, 0, (len + 7) / 8);
}

BitMap::~BitMap()
{
    testNum_--;
    if (m_bmp) {
        delete[] m_bmp;
        m_bmp = NULL;
    }
    m_size  = 0;
    m_count = 0;
}

bool BitMap::Get(size_t n)
{
    if (n < m_size) {
        return (m_bmp[n / 8] >> n % 8) & 1;
    } else {
        return false;
    }
}

void BitMap::Set(size_t n, bool val)
{
    if (n < m_size) {
        unsigned char t = 1 << n % 8;
        if (val) {
            if (!Get(n)) {
                m_count++;
            }
            m_bmp[n / 8] |= t;
        } else {
            if (Get(n)) {
                m_count--;
            }
            m_bmp[n / 8] &= ~t;
        }
    }
}

bool BitMap::ToBuf(void* buf, size_t len)
{
    size_t currentByte = (m_size + 7) / 8;
    if (len >= currentByte) {
        memcpy(buf, m_bmp, currentByte);
        return true;
    }
    return false;
}

bool BitMap::FromBuf(void* buf, size_t len)
{
    size_t currentByte = (m_size + 7) / 8;
    if (len >= currentByte) {
        memcpy(m_bmp, buf, currentByte);
        ReCount();
        return true;
    }
    return false;
}

size_t BitMap::GetSpace()
{
    return (m_size + 7) / 8;
}

unsigned char* BitMap::GetSpaceData()
{
    return m_bmp;
}

void BitMap::Reset()
{
    memset(m_bmp, 0, (m_size + 7) / 8);
    m_count = 0;
}

size_t BitMap::Size()
{
    return m_size;
}

size_t BitMap::Count()
{
    return m_count;
}

bool BitMap::Full()
{
    bool bRet = false;
    if (m_size > 0 && m_size == m_count) {
        bRet = true;
    }
    return bRet;
}

void BitMap::ReCount()
{
    m_count = 0;
    for (size_t i = 0; i < m_size; ++i) {
        bool bSet = (m_bmp[i / 8] >> i % 8) & 1;
        if (bSet) {
            m_count++;
        }
    }
}

const BitMap& BitMap::operator=(const BitMap& id)
{
    if (this != &id) {
        m_size  = id.m_size;
        m_count = id.m_count;
        if (m_bmp) {
            delete[] m_bmp;
        }
        size_t dataLen = (m_size + 7) / 8;
        m_bmp          = new unsigned char[dataLen];
        memcpy(m_bmp, id.m_bmp, dataLen);
    }
    return *this;
}
